#pragma once

#include "../UIElement.h"
#include "../IUITextElement.h"

class UICheckbox : public UIElement, public IUITextElement
{
public:
	UICheckbox();
	UICheckbox(float xPos, float yPos);
	UICheckbox(float xPos, float yPos, float size);
	UICheckbox(float xPos, float yPos, float size, std::string text);
	UICheckbox(float xPos, float yPos, float size, std::string text, std::string fontName);
	UICheckbox(float xPos, float yPos, float size, std::string text, std::string fontName, int fontSize);
	UICheckbox(float xPos, float yPos, float size, std::string text, std::string fontName, int fontSize, float margins);

	// Draws the element on the screen and has to be called between graphics.BeginDraw() and graphics.EndDraw()
	void __stdcall Draw(Graphics* graphics);

	bool Checked = false;
	float Size = 20.0f;
	float Margins = 4.0f;
	bool RoundedCorners = true;
	float RoundCornerRadiusX = 4.0f, RoundCornerRadiusY = 4.0f;
	int CheckmarkFontSize = FontSize;
	Color CheckmarkColor = Color::Black;

	// Sets enabled state of the checkbox
	void SetEnabled(bool state)
	{
		this->enabled = state;
		if (state)
		{
			color.a = normalAlpha;
			TextColor.a = normalAlpha;
			CheckmarkColor.a = normalAlpha;
		}
		else
		{
			color.a = 36;
			TextColor.a = 36;
			CheckmarkColor.a = 36;
		}
	}

	// Fades the element out over given period of time in miliseconds
	void __stdcall FadeOut(int time)
	{
		std::thread fadeout_thread([this, &time]
		{
			Color currentColor = color;
			float currentAlpha = currentColor.a;
			if (currentAlpha == 0) { currentAlpha = 1; }
			int sleepIntervals = time / (int)currentAlpha;
			for (int i = (int)currentAlpha; i > 0; i--)
			{
				currentColor.a--;
				color = currentColor;

				Color newTextColor = TextColor;
				newTextColor.a = currentColor.a;
				CheckmarkColor.a = currentColor.a;
				TextColor = newTextColor;

				Sleep(sleepIntervals);
			}
			Visible = false;
		});
		fadeout_thread.join();
	}

	// Fades the element in over given period of time in miliseconds until the needed alpha value is reached
	void __stdcall FadeIn(int time, int finalAlpha = 255)
	{
		int sleepInterval = 0;
		if (finalAlpha < color.a) return; // invalid alpha state
		int delta = finalAlpha - color.a;
		if (delta == 0)
		{
			sleepInterval = time;
		}
		else
		{
			sleepInterval = time / delta;
		}

		if (finalAlpha >= 255)
			finalAlpha = 254;

		std::thread fadein_thread([this, sleepInterval, finalAlpha] {
			Visible = true;
			for (int i = color.a; i <= finalAlpha; i++)
			{
				Sleep(sleepInterval);
				uint8_t val = (uint8_t)i;
				color.a = val;


				Color newTextColor = TextColor;
				newTextColor.a = color.a;
				CheckmarkColor.a = color.a;
				TextColor = newTextColor;

				this->normalAlpha = color.a;
			}
		});
		fadein_thread.detach();
	}

	// Adds a callback event for when the checked state of the checkbox changes
	void AddCheckEvent(callback_function evt) { m_CheckedStateChangedEvents.push_back(evt); }

private:
	void SetupEventListeners();

	std::vector<callback_function> m_CheckedStateChangedEvents;
};

